package main;
import java.io.Serializable;
import java.text.DateFormatSymbols;
/**
 * The Class WorldState which holds all of the information about the current state of the game.
 */
public class WorldState implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5265099352838640777L;
	private TravelGroup travelGroup;
	private int totalDistanceTraveled;
   	private Location currentLocation;
    private int month, dayOfMonth, year;
    private boolean firstMove;
	/**
	 * @param month
	 *            the current month
	 * @param dayOfMonth
	 *            the current day
	 * @param travelGroup
	 *            the travelGroup
	 */
	public WorldState(int month, int dayOfMonth, TravelGroup travelGroup) {
		this.travelGroup = travelGroup;
        generateMap();
        totalDistanceTraveled = 0;
        this.month = month;
        this.dayOfMonth = dayOfMonth;
        this.year = 1885;
        firstMove = true;
	}
        
        public WorldState(){
            this(0,0,new TravelGroup());
        }
	
    public void generateMap(){
    	Landmark dalles = new Landmark("Dalles", new Trail(0, new Landmark()));
    	Trail trail15 = new Trail(120, dalles);
    	Landmark fortWallaWalla = new Fort("Fort Walla Walla", trail15, new Store(.5));
    	Trail trail14 = new Trail(55, fortWallaWalla);
    	Landmark blueMountains = new Landmark("Blue Mountains", trail14);
    	Trail trail13 = new Trail(162, blueMountains);
    	Landmark fortBoise = new Fort("Fort Boise", trail13, new Store(1.3));	//KELLEN MOORE FOR HEISMAN!!!!
    	Trail trail12 = new Trail(114, fortBoise);
    	Landmark snakeRiver = new River("Snake River Crossing", trail12, 4, 8);
    	Trail trail11 = new Trail(182, snakeRiver);
    	Landmark fortHall = new Fort("Fort Hall", trail11, new Store(.7));
    	Trail trail10 = new Trail(57, fortHall);
    	Landmark sodaSprings = new Landmark("Soda Springs", trail10);
    	Trail trail9 = new Trail(162, sodaSprings);
    	Landmark fortBridger = new Fort("Fort Bridger", trail9, new Store(1.5));
    	Trail trail8 = new Trail(125, fortBridger);
    	Landmark southPass = new Landmark("South Pass", trail8);
    	Trail trail7 = new Trail(102, southPass);
    	Landmark independenceRock = new Landmark("Independence Rock", trail7);
    	Trail trail6 = new Trail(190, independenceRock);
    	Landmark fortLaramie = new Fort("Fort Laramie", trail6, new Store(.9));
    	Trail trail5 = new Trail(86, fortLaramie);
    	Landmark chimneyRock = new Landmark("Chimney Rock", trail5);
    	Trail trail4 = new Trail(250, chimneyRock);
    	Landmark ftKearny = new Fort("Ft Kearny", trail4, new Store(1.2));
    	Trail trail3 = new Trail(119, ftKearny);
    	Landmark bigBlue = new River("Big Blue", trail3, 2, 4);
    	Trail trail2 = new Trail(83, bigBlue);
    	Landmark kansasRiver = new River("Kansas River", trail2, 6, 10);
    	Trail trail1 = new Trail(102, kansasRiver);
    	
    	this.currentLocation = new Fort("Independence, Missouri", trail1, new Store());
    }

	/**
     * This method updates the group's location and the amount of food it has
     * 
     * recent additions by @author Jarvis
     */
    public void updateWorldState(){
        
    	if(firstMove) {
    		currentLocation = ((Landmark)currentLocation).getNext();
    		firstMove = false;
    	}
    	
        //dirty things
    	//we've poorly defined how to handle landmarks, i propose we roll
    	//landmark into trail and handle it via some sort of inherited boolean
    	//value. also i'm not sure how being at a store is different.
    	if(!(currentLocation instanceof Landmark)) {
    		// current location as a trail
        	Trail trail = (Trail) currentLocation;
        	// current miles we will be traveling this turn
        	int currentPace = travelGroup.calculateTravelPace();
        	//incrementing total distance by our travel this turn
        	totalDistanceTraveled += currentPace;
        	// update progress on the current location
            trail.setProgress(trail.getProgress() + currentPace);
            // how far we have left to go on this location
            int toGo = trail.getDistance()-trail.getProgress();
            //if we pass the location this turn, advance to the next location
            if(toGo <= 0) {
            	currentLocation = trail.getNextLandmark();
            	trail.setProgress(Math.abs(toGo));
            }
    	} else {
    		currentLocation = ((Landmark)currentLocation).getNext();
    	}
    	
        // they eat food for a turn
        travelGroup.calculateRations();
        // day++
        advanceDay();
       
        
        
    }
    public void advanceDay() {
    	 int[] lengthOfMonth = {31,28,31,30,31,30,31,31,30,31,30,31};
         if(dayOfMonth==lengthOfMonth[month-1]){
         	dayOfMonth = 1;
         	if(month==12){
         		month = 1;
         		year++;
         	}
         	month++;
         }
         else dayOfMonth++;
    }
    /**
     * Getter for total distance traveled
     * @return Total distance traveled
     */
    public int getTotalDistanceTraveled() {
		return totalDistanceTraveled;
	}  
        /**
	 * @return the TravelGroup
	 */
	public TravelGroup getTravelGroup() {
		return travelGroup;
	}

	/**
	 * @param travelGroup
	 *            the TravelGroup
	 */
	public void setTravelGroup(TravelGroup travelGroup) {
		this.travelGroup = travelGroup;
	}


	/**
	 * @return the date in String form
	 */
	public String getDate(){
		DateFormatSymbols dfs = new DateFormatSymbols();
		String[] months = dfs.getMonths();
		return (months[month-1]+" "+dayOfMonth+", "+year);
		
	}
    /**
     * @return the currentLocation
     */
    public Location getCurrentLocation() {
        return currentLocation;
    }

    /**
     * @param currentLocation the currentLocation to set
     */
    public void setCurrentLocation(Location currentLocation) {
        this.currentLocation = currentLocation;
    }

	/**
	 * @param month the month to set
	 */
	public void setMonth(int month) {
		this.month = month;
	}

	/**
	 * @param dayOfMonth the dayOfMonth to set
	 */
	public void setDayOfMonth(int dayOfMonth) {
		this.dayOfMonth = dayOfMonth;
	}

	/**
	 * @param year the year to set
	 */
	public void setYear(int year) {
		this.year = year;
	}

	/**
	 * @return the month
	 */
	public int getMonth() {
		return month;
	}

	/**
	 * @return the dayOfMonth
	 */
	public int getDayOfMonth() {
		return dayOfMonth;
	}

	/**
	 * @return the year
	 */
	public int getYear() {
		return year;
	}

}



